package com.ymatou.iapi.delivery.testcase;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.google.common.collect.Lists;
import com.ymatou.iapi.delivery.parameter.DeliveryInfo;
import com.ymatou.iapi.delivery.parameter.XloboDeliverGoodsReq;
import com.ymatou.iapi.delivery.parameter.enums.CheckBizResultEnum;
import com.ymatou.iapi.delivery.parameter.resp.DeliveryCheckResp;
import com.ymatou.iapi.delivery.parameter.resp.DeliveryCheckResult;
import com.ymatou.iapi.delivery.parameter.resp.ExpectCheckResult;
import com.ymatou.iapi.delivery.service.DeliveryService;
import com.ymatou.iapi.delivery.service.XloboDeliverGoodsCall;
import com.ymatou.iapi.optrade.parameter.enums.LogisticsTypeEnum;
import com.ymatou.iapi.optrade.parameter.utill.Utils;
import com.ymatou.iapi.optrade.resp.TradingServiceResp;
import com.ymatou.iapi.synctrade.service.TradingSyncService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.YMTTrading.TradingCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceOrderCallService;
import com.ymttest.database.sharding.db.ext.model.DeliveryPo;
import com.ymttest.database.sharding.db.sharding.model.AutoReceiveOptDetailPo;
import com.ymttest.database.sharding.db.sharding.model.AutoReceiveOptPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sharding.model.OrderStatusLogPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sharding.db.sqlwapper.OrderWapper;

/**
 * 物流发货接口 FreeMaker Template自动生成代码
 */
@TestSuite
public class Ts_XloboDeliverGoods {

	private static XloboDeliverGoodsReq xloboDeliverGoodsReq;
	private static XloboDeliverGoodsCall xloboDeliverGoodsCall;
	
	private static String xloboBillNo = "DB2533011979US";

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("贝海发货接口-新");
	}

	@Before
	public void caseUp() {
		xloboDeliverGoodsReq = new XloboDeliverGoodsReq();
		xloboDeliverGoodsCall = new XloboDeliverGoodsCall();
	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(xloboDeliverGoodsCall.getOpurl());
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 
	 * @param expectCheckResultList
	 */
	private void verify(List<ExpectCheckResult> expectCheckResultList) {

		DeliveryCheckResp resp = xloboDeliverGoodsCall.getDeliveryCheckResp();

		List<DeliveryCheckResult> billNoCheckResults = resp.getResults();

		int i = 0;

		for (ExpectCheckResult expectcheckResultInfo : expectCheckResultList) {

			DeliveryCheckResult checkResult = billNoCheckResults.get(i);

			Logger.verifyEquals(expectcheckResultInfo.isBizSuccess(),
					checkResult.isBizSuccess(), "校验BizSuccess");

			if (checkResult.isBizSuccess()) {

				// 交易订单状态数据
				verifyOrderStatus(expectcheckResultInfo.getDeliveryInfo(),
						xloboDeliverGoodsReq.getSellerId(), false, expectcheckResultInfo.getOrderStatus());
			}

			Logger.verifyEquals(expectcheckResultInfo.getBizCode(),
					checkResult.getBizCode(), "校验bizCode");

			Logger.verifyEquals(expectcheckResultInfo.getBizMsg(),
					checkResult.getBizMsg(), "校验bizMsg");


			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getBillNo(), checkResult.getBillNo(), "校验billNo");

			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getOrderId(), checkResult.getOrderId(), "校验orderId");


			Logger.verifyEquals(expectcheckResultInfo.getDeliveryInfo()
					.getYmtExpressCode(), checkResult.getYmtExpressCode(),
					"校验ymtExpressCode");

			i++;
		}
	}

	/**
	 * 校验自动确认收货时间操作详情表（auto_receive_opt_detail）
	 */
	private void verifyAutoReceiveDetail(long orderId,
			boolean isShippedByXlobo, boolean isFreeze) {

		AutoReceiveOptDetailPo actual = new OrderShardingWapper()
				.selectAutoReceiveOptDetailByOrderId(orderId);

		Logger.comment(String.format(
				"验证自动确认收货时间操作详情表（auto_receive_opt_detail）  orderId: %s",
				orderId));

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(actual.getAddTime()) < 2,
				"验证数据库AddTime跟系统当前时间差为2分钟内");
		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(actual.getUpdateTime()) < 2,
				"验证数据库UpdateTime跟系统当前时间差为2分钟内");

		int bizType = 1;

		if (!isShippedByXlobo) {
			bizType = 2;
		}

		Logger.verifyEquals(orderId, actual.getOrderId(), "验证数据库OrderId");

		Logger.verifyEquals(bizType, actual.getBizType(), "验证数据库BizType");

		Logger.verifyEquals(isFreeze, actual.getFreeze(), "验证数据库Freeze");

		if (!isFreeze) {
			Logger.verifyEquals(true,
					Utils.calcTimeSpanMin(actual.getUnfreezeTime()) < 2,
					"验证数据库UnfreezeTime跟系统当前时间差为2分钟内");

		} else {
			Logger.verifyEquals(null, actual.getUnfreezeTime(),
					"验证数据库UnfreezeTime跟系统当前时间差为2分钟内");
		}

		verifyAutoReceive(orderId, isFreeze);

	}

	/**
	 * 校验自动确认收货时间操作表（auto_receive_opt）
	 */
	private void verifyAutoReceive(long orderId, boolean isFreeze) {

		// 自动确认收货时间操作表（auto_receive_opt）
		AutoReceiveOptPo autoReceiveOptPo = new OrderShardingWapper()
				.selectAutoReceiveOptByOrderId(orderId);

		Logger.comment(String.format(
				"验证自动确认收货时间操作表（auto_receive_opt）  orderId: %s", orderId));

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(autoReceiveOptPo.getAddTime()) < 2,
				"验证数据库AddTime跟系统当前时间差为2分钟内");
		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(autoReceiveOptPo.getUpdateTime()) < 2,
				"验证数据库UpdateTime跟系统当前时间差为2分钟内");

		Logger.verifyEquals(orderId, autoReceiveOptPo.getOrderId(),
				"验证数据库OrderId");
		Logger.verifyEquals(isFreeze, autoReceiveOptPo.getFreeze(),
				"验证数据库Freeze");

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(autoReceiveOptPo.getFreezeTime()) < 2,
				"验证数据库FreezeTime跟系统当前时间差为2分钟内");

		/*
		 * Logger.verifyEquals(null, autoReceiveOptPo.getExpectReceiveTime(),
		 * "验证数据库ExpectReceiveTime");
		 */

	}

	/**
	 * 校验订单表状态，单主状态操作日志表
	 */
	private void verifyOrderStatus(DeliveryInfo info, long sellerId,
			boolean isShippedByXlobo, Integer orderStatus) {

		OrderShardingWapper orderShardingWapper = new OrderShardingWapper();

		long orderId = info.getOrderId();

		// 订单表(order)
		OrderPo ymtOrders = orderShardingWapper.selectOrderbyOrderId(orderId);

		Logger.comment(String.format("验证订单表(order)表 orderId: %s", orderId));

		Logger.verifyEquals(orderStatus, ymtOrders.getOrderStatus(), "验证orderStatus");

		Logger.verifyEquals(
				info.getExpressName()
						.equalsIgnoreCase("洋码头官方合作物流（xLobo贝海国际速递）"), ymtOrders
						.getXloboDelivery(), "验证xloboDelivery");

		Logger.verifyEquals(info.getDeliverySection() == 3 && orderStatus == 3,
				ymtOrders.getDomesticDelivery(), "验证domesticDelivery");
		
		// 国际段有鉴定包裹，国内段无鉴定包裹 或者 国际段有普通包裹，国内段无普通包裹
		Logger.verifyEquals(true,
				ymtOrders.getSupplementDomestic(), "验证SupplementDomestic");

		Logger.verifyEquals(true,
				Utils.calcTimeSpanMin(ymtOrders.getDeliveryTime()) < 2,
				"验证数据库deliveryTime跟系统当前时间差为2分钟内");
		
		if (orderStatus == 3) {
			
			// 订单主状态操作日志表(order_status_log)
			OrderStatusLogPo orderStatusLogPo = orderShardingWapper
					.selectOrderStatusLogByOrderId(orderId);

			Logger.comment("验证订单主状态操作日志表(order_status_log)");

			Logger.verifyEquals("发货", orderStatusLogPo.getMemo(), "验证数据库Memo");
			Logger.verifyEquals(3, orderStatusLogPo.getOrderStatus(),
					"验证数据库OrderStatus");

			Logger.verifyEquals(true,
					Utils.calcTimeSpanMin(orderStatusLogPo.getAddTime()) < 2,
					"验证数据库AddTime跟系统当前时间差为2分钟内");

			Logger.verifyEquals(orderId, orderStatusLogPo.getOrderId(),
					"验证数据库OrderId");
			Logger.verifyEquals(sellerId, orderStatusLogPo.getOperator(),
					"验证数据库Operator");

			if (ymtOrders.getLogisticsType() == 7 && !ymtOrders
					.getDomesticDelivery()) {
				verifyAutoReceiveDetail(orderId, false, !ymtOrders
						.getDomesticDelivery().equals(true));
			}

			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			verifyMysqlDb(info, sellerId, ymtOrders.getLogisticsType(),
					ymtOrders.getOfficialLogistics());
		}
	}

	/**
	 * 校验 mysql delivery 表
	 * 
	 * @param info
	 */
	private void verifyMysqlDb(DeliveryInfo info, long sellerId,
			int logisticsType, Boolean officialLogistics) {

		long orderId = info.getOrderId();
		
		DeliveryPo actualDeliveryPo = new OrderWapper()
				.selectDeliveryByOrderIdAndBillCode(orderId, info.getBillNo());

		Logger.comment("校验 delivery 表数据 billNo: " + info.getBillNo());

		Logger.verifyEquals(info.getYmtExpressCode(),
				actualDeliveryPo.getYmtExpressCode(), "验证数据库YmtExpressCode");

		Logger.verifyEquals(true, actualDeliveryPo.getOfficalLogistics(),
				"验证数据库OfficalLogistics");

		Logger.verifyEquals(Utils.zeroIfNull(info.getRealDeliveryArea()),
				actualDeliveryPo.getRealDeliveryArea(), "验证数据库RealDeliveryArea");

		Logger.verifyEquals(orderId, actualDeliveryPo.getOrderId(),
				"验证数据库OrderId");

		Logger.verifyEquals(sellerId, actualDeliveryPo.getSellerId(),
				"验证数据库SellerId");

		Logger.verifyEquals(logisticsType, actualDeliveryPo.getLogisticsType(),
				"验证数据库LogisticsType");

		Logger.verifyEquals(false, actualDeliveryPo.getDeleted(),
				"验证数据库Deleted");

		Logger.verifyEquals(info.getDeliverySource(),
				actualDeliveryPo.getSource(), "验证数据库Source");
		
		Logger.verifyEquals(false, actualDeliveryPo.getSourceTrack(),
				"验证数据库SourceTrack");

		Logger.verifyEquals(info.getBillNo(), actualDeliveryPo.getBillNo(),
				"验证数据库BillNo");

		Logger.verifyEquals(info.getDeliverySection(),
				actualDeliveryPo.getSection(), "验证数据库Section");

		Logger.verifyEquals(info.getMobile(), actualDeliveryPo.getMobile(),
				"验证数据库Mobile");
		
		Logger.verifyEquals(
				Utils.falseIfNull(info.getAuthenticatePackage()) ? 1 : 0,
				actualDeliveryPo.getPackageType(), "验证数据库PackageType");
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_deliverGoods_001() {
		Logger.start(true, "境外发货 国际段  贝海物流，发货成功");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithLogisticsType(LogisticsTypeEnum.OVERSEAS_DELIVERY);

			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();

			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();

			long userId = placeOrderResp.getUserId();

			long tradingId = placeOrderResp.getTradingId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);

			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			TradingSyncService.getSyncResult(orderId);

			DeliveryInfo dInfo = new DeliveryInfo();

			dInfo.setOrderId(orderId);

			dInfo.setBillNo(xloboBillNo);

			// 发货节点、1国际段,2转运段,3国内段
			dInfo.setDeliverySection(1);
			dInfo.setDeliverySource(1);

			dInfo.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo.setYmtExpressCode("Y068");

			xloboDeliverGoodsReq.setDeliveryInfos(Lists.newArrayList(dInfo));

			xloboDeliverGoodsReq.setSellerId(sellerId);

			xloboDeliverGoodsCall.setData(xloboDeliverGoodsReq);
			xloboDeliverGoodsCall.callService();

			Logger.verifyEquals(xloboDeliverGoodsCall.getSuccess(), true,
					"校验IsSuccess");

			List<ExpectCheckResult> list = new ArrayList<ExpectCheckResult>();

			xloboDeliverGoodsReq
					.getDeliveryInfos()
					.forEach(
							item -> {

								ExpectCheckResult expectCheckResult = new ExpectCheckResult(
										item);

								expectCheckResult
										.setBizCode(CheckBizResultEnum.passed
												.getCode());
								expectCheckResult
										.setBizMsg(CheckBizResultEnum.passed
												.getMessage());

								expectCheckResult.setBizSuccess(true);
								expectCheckResult.setValidation(true);

								expectCheckResult.setLogisticsType(7);
								expectCheckResult.setMicroShopOrder(false);
								expectCheckResult.setOrderStatus(3);

								list.add(expectCheckResult);

							});
			
			Thread.sleep(5000);

			verify(list);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_deliverGoods_002() {
		Logger.start(true, "境外发货 国际段  贝海物流发多个包裹，运单号一样，发货成功");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithLogisticsType(LogisticsTypeEnum.OVERSEAS_DELIVERY);

			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();

			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();

			long userId = placeOrderResp.getUserId();

			long tradingId = placeOrderResp.getTradingId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);

			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			TradingSyncService.getSyncResult(orderId);

			DeliveryInfo dInfo = new DeliveryInfo();

			dInfo.setOrderId(orderId);

			dInfo.setBillNo(xloboBillNo);

			// 发货节点、1国际段,2转运段,3国内段
			dInfo.setDeliverySection(1);
			dInfo.setDeliverySource(1);

			dInfo.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo.setYmtExpressCode("Y068");
			
			DeliveryInfo dInfo2 = new DeliveryInfo();

			dInfo2.setOrderId(orderId);

			dInfo2.setBillNo(xloboBillNo);

			// 发货节点、1国际段,2转运段,3国内段
			dInfo2.setDeliverySection(1);
			dInfo2.setDeliverySource(1);

			dInfo2.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo2.setYmtExpressCode("Y068");

			xloboDeliverGoodsReq.setDeliveryInfos(Lists.newArrayList(dInfo, dInfo2));

			xloboDeliverGoodsReq.setSellerId(sellerId);

			xloboDeliverGoodsCall.setData(xloboDeliverGoodsReq);
			xloboDeliverGoodsCall.callService();

			Logger.verifyEquals(xloboDeliverGoodsCall.getSuccess(), true,
					"校验IsSuccess");

			List<ExpectCheckResult> list = new ArrayList<ExpectCheckResult>();

			xloboDeliverGoodsReq
					.getDeliveryInfos()
					.forEach(
							item -> {

								ExpectCheckResult expectCheckResult = new ExpectCheckResult(
										item);

								expectCheckResult
										.setBizCode(CheckBizResultEnum.billNoRepeat
												.getCode());
								expectCheckResult
										.setBizMsg(CheckBizResultEnum.billNoRepeat
												.getMessage());

								expectCheckResult.setBizSuccess(false);
								expectCheckResult.setValidation(false);

								expectCheckResult.setLogisticsType(7);
								expectCheckResult.setMicroShopOrder(false);
								expectCheckResult.setOrderStatus(3);

								list.add(expectCheckResult);

							});
			
			Thread.sleep(5000);

			verify(list);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({ P1.class })
	@TestCase
	public void Tc_deliverGoods_003() {
		Logger.start(true, "境外发货 国际段  贝海物流发多个包裹，运单号不一样，再次发货，修改运单号，发货成功");
		try {

			DeliveryService.deleteDeliverByBillNo(xloboBillNo);
			DeliveryService.deleteDeliverByBillNo("DB2533011978US");
			
			// 第一个订单，第一次发货
			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithLogisticsType(LogisticsTypeEnum.OVERSEAS_DELIVERY);

			long sellerId = placeOrderResp.getOrderList().get(0).getSellerId();

			long orderId = placeOrderResp.getOrderList().get(0).getOrderId();

			long userId = placeOrderResp.getUserId();

			long tradingId = placeOrderResp.getTradingId();

			BigDecimal useAccountAmount = placeOrderResp.getPayableAmount();

			TradingCallService.payOrder(userId, useAccountAmount, tradingId);

			TradingCallService.sellerAcceptOrder(sellerId, orderId);

			TradingSyncService.getSyncResult(orderId);

			DeliveryInfo dInfo = new DeliveryInfo();

			dInfo.setOrderId(orderId);

			dInfo.setBillNo(xloboBillNo);

			// 发货节点、1国际段,2转运段,3国内段
			dInfo.setDeliverySection(1);
			dInfo.setDeliverySource(1);

			dInfo.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo.setYmtExpressCode("Y068");
			
			DeliveryInfo dInfo2 = new DeliveryInfo();

			dInfo2.setOrderId(orderId);

			dInfo2.setBillNo("DB2533011978US");

			// 发货节点、1国际段,2转运段,3国内段
			dInfo2.setDeliverySection(1);
			dInfo2.setDeliverySource(1);

			dInfo2.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo2.setYmtExpressCode("Y068");

			xloboDeliverGoodsReq.setDeliveryInfos(Lists.newArrayList(dInfo, dInfo2));

			xloboDeliverGoodsReq.setSellerId(sellerId);

			xloboDeliverGoodsCall.setData(xloboDeliverGoodsReq);
			xloboDeliverGoodsCall.callService();
			
			// 第二次发货
			DeliveryInfo dInfo3 = new DeliveryInfo();

			dInfo3.setOrderId(orderId);

			dInfo3.setBillNo(xloboBillNo);

			// 发货节点、1国际段,2转运段,3国内段
			dInfo3.setDeliverySection(1);
			dInfo3.setDeliverySource(1);

			dInfo3.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo3.setYmtExpressCode("Y068");

			DeliveryInfo dInfo4 = new DeliveryInfo();

			dInfo4.setOrderId(orderId);

			dInfo4.setBillNo("DB2555011977US");

			// 发货节点、1国际段,2转运段,3国内段
			dInfo4.setDeliverySection(1);
			dInfo4.setDeliverySource(1);

			dInfo4.setExpressName("洋码头官方合作物流（xLobo贝海国际速递）");
			dInfo4.setYmtExpressCode("Y068");

			xloboDeliverGoodsReq.setDeliveryInfos(Lists.newArrayList(dInfo3,
					dInfo4));

			xloboDeliverGoodsReq.setSellerId(sellerId);

			xloboDeliverGoodsCall.setData(xloboDeliverGoodsReq);
			xloboDeliverGoodsCall.callService();

			Logger.verifyEquals(xloboDeliverGoodsCall.getSuccess(), true,
					"校验IsSuccess");

			List<ExpectCheckResult> list = new ArrayList<ExpectCheckResult>();

			xloboDeliverGoodsReq
					.getDeliveryInfos()
					.forEach(
							item -> {

								ExpectCheckResult expectCheckResult = new ExpectCheckResult(
										item);

								expectCheckResult
										.setBizCode(CheckBizResultEnum.passed
												.getCode());
								expectCheckResult
										.setBizMsg(CheckBizResultEnum.passed
												.getMessage());

								expectCheckResult.setBizSuccess(true);
								expectCheckResult.setValidation(true);

								expectCheckResult.setLogisticsType(7);
								expectCheckResult.setMicroShopOrder(false);
								expectCheckResult.setOrderStatus(3);

								list.add(expectCheckResult);

							});
			
			Thread.sleep(5000);

			verify(list);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}